[Terraform] EC2のEBS追加ボリュームをサイズ拡張しようとしたらハマった話
こんにちは!コンサル部のinomaso(@inomasosan)です。
検証時や案件対応時にはTerraformでEC2を作成することが多いです。
ある日、EBSルートボリューム以外のEBS追加ボリュームのサイズ拡張が必要となったのですが、サイズの変更を検出しなかったりEC2自体を再作成するような挙動がみられたので調査してみました。
先に結論
ebs_block_device
は初回のリソース作成時にのみ適用されるため、リソース作成後の変更は検出されない。- DBやファイルサーバ等の用途で、将来的にEBS追加ボリュームのサイズ変更が必要な場合は、
aws_ebs_volume
とaws_volume_attachment
を使用すること。- ただし、
delete_on_termination
オプションが存在しないため注意。
- ただし、
検証環境
今回実行した環境は以下の通りです。
項目 | バージョン |
---|---|
Terraform | 1.7.4 |
AWSプロバイダー | 5.38.0 |
事象について
以下のコードは、Amazon Linux 2023を作成した際のEBSボリューム部分の抜粋です。
EBS追加ボリュームはebs_block_device
で定義しています。
resource "aws_instance" "main" { ~中略~ # EBSルートボリューム root_block_device { # ボリュームサイズ(GiB) volume_size = 8 # ボリュームタイプ volume_type = "gp3" # GP3のIOPS iops = 3000 # GP3のスループット throughput = 125 # EC2終了時に削除 delete_on_termination = true # EBS暗号化 encrypted = "true" # EBSのNameタグ tags = { Name = "inomaso-dev-ec2-xvda" } } # EBS追加ボリューム ebs_block_device { device_name = "/dev/sdf" # ボリュームサイズ(GiB) volume_size = 8 # ボリュームタイプ volume_type = "gp3" # GP3のIOPS iops = 3000 # GP3のスループット throughput = 125 # EC2終了時に削除 delete_on_termination = true # EBS暗号化 encrypted = "true"<br /> # EBSのNameタグ tags = { Name = "inomaso-dev-ec2-sdf" } } }
EBSルートボリュームのサイズ拡張は、root_block_device
のvolume_size
を変更すれば、terraform apply
やterraform plan
を実行時に該当部分の変更を検出してくれます。
一方で、EBS追加ボリュームのサイズ拡張は、ebs_block_device
のvolume_size
を変更しても、変更が検出されずNo changesと出力されます。
また、ebs_block_device
ブロック自体を追加すると、EC2自体を再作成するような挙動になることがわかりました。
原因について
Terraform公式ドキュメントを確認したところ、以下のような記載がありました。
Currently, changes to the ebs_block_device configuration of existing resources cannot be automatically detected by Terraform. To manage changes and attachments of an EBS block to an instance, use the aws_ebs_volume and aws_volume_attachment resources instead. If you use ebs_block_device on an aws_instance, Terraform will assume management over the full set of non-root EBS block devices for the instance, treating additional block devices as drift. For this reason, ebs_block_device cannot be mixed with external aws_ebs_volume and aws_volume_attachment resources for a given instance.
ebs_block_device
は初回のリソース作成時にのみ適用され、以降は変更を検出することができない仕様のようです。
変更を検出させたい場合はaws_ebs_volume
とaws_volume_attachment
を使用する必要があるようです。
改善してみたものの思わぬ落とし穴が
ebs_block_device
ブロックを削除して、aws_ebs_volume
とaws_volume_attachment
で書き直してみました。
resource "aws_instance" "main" { ~中略~ # EBSルートボリューム root_block_device { # ボリュームサイズ(GiB) volume_size = 8 # ボリュームタイプ volume_type = "gp3" # GP3のIOPS iops = 3000 # GP3のスループット throughput = 125 # EC2終了時に削除 delete_on_termination = true # EBS暗号化 encrypted = "true" # EBSのNameタグ tags = { Name = "inomaso-dev-ec2-xvda" } } } # EBS追加ボリューム resource "aws_ebs_volume" "sdf" { availability_zone = "ap-northeast-1a" # ボリュームサイズ(GiB) size = 8 # ボリュームタイプ type = "gp3" # GP3のIOPS iops = 3000 # GP3のスループット throughput = 125 # EBS暗号化 encrypted = "true" # EBSのNameタグ tags = { Name = "inomaso-dev-ec2-sdf" } } resource "aws_volume_attachment" "sdf" { device_name = "/dev/sdf" volume_id = aws_ebs_volume.sdf.id instance_id = aws_instance.main.id }
リソース作成後にsize
を変更したところ、ちゃんと変更を検出してくれました。
ただしこの書き方の場合に一つ落とし穴がありました。
それはdelete_on_termination
オプションが存在しないことです。
例えばTerraform以外でEC2を削除した際に、EBS追加ボリュームはEC2と一緒に削除されません。
現状はAWS CLI等で対応する必要があるのですが、対象数が多い場合は以下のブログを参考に対応すると良いでしょう。
将来的な改善
調べてみたところ、delete_on_termination
オプションを追加するプルリクがオープンされていました。
そのうち対応されることを願いつつ、現状はTerraform + AWS CLIで急場を凌ぎたく思います。
まとめ
TerraformでEC2の構築はこれまでたくさんやってきましたが、思わぬ落とし穴にハマりびっくりしました。 改めて公式ドキュメントをしっかり確認することの大切さを痛感しました。
この記事が、どなたかのお役に立てば幸いです。それでは!